
#include "thttpd.h"
#include "shmem.h"
#include "list.h"
#include "modbus.h"
#include "common.h"

// 外部引用链表头
extern struct list_head head;
struct shm_param para;
static int *total = NULL;
static struct std_node *node_arr = NULL;
pthread_mutex_t mutex;

// 数据采集线程
void *dataacquisition(void *arg)
{
    printf("数据采集线程启动\n\n");
    printf("------------------------------------------\n");
    modbus_t *ctx = (modbus_t *)arg;
    uint16_t dest1;
    uint8_t dest;
    int rc;

    // 初始化共享内存
    if (shm_init(&para, SHM_NAME, SHM_SIZE) < 0)
    {
        fprintf(stderr, "共享内存初始化失败\n");
        return NULL;
    }

    void *shm_addr = shm_getaddr(&para);
    if (shm_addr == NULL)
    {
        fprintf(stderr, "获取共享内存地址失败\n");
        return NULL;
    }

    total = (int *)shm_addr;
    node_arr = (struct std_node *)(total + 1);

    while (1)
    {
        struct list_head *pos;
        list_for_each(pos, &head)
        {
            struct mb_node_list *mb_node = list_entry(pos, struct mb_node_list, list);

            int found = 0;
            printf("开始采集数据,并存入共享内存\n");
            for (int i = 0; i < *total; i++)
            {
                printf("正在查询共享内存节点:%d\n",node_arr[i].key);
                if (node_arr[i].key == mb_node->node.key)
                {
                    found = 1;
                    printf("找到节点:%d\n",mb_node->node.key);

                    // 根据类型读取数据
                    switch (mb_node->node.type)
                    {
                    case 1: // 线圈状态 (开关量)
                        rc = modbus_read_bits(ctx, mb_node->node.addr, 1, &dest);
                        if (rc == 1)
                        {
                            node_arr[i].old_val = node_arr[i].new_val;
                            node_arr[i].new_val.i_val = dest;
                            node_arr[i].ret = 0;
                            printf("线圈[%d]读取成功: %s = %d\n",
                                   mb_node->node.addr, mb_node->node.name, dest);
                        }
                        else
                        {
                            node_arr[i].ret = -1;
                            fprintf(stderr, "线圈读取失败: %s\n", modbus_strerror(errno));
                        }
                        break;

                    case 2:
                    { // 保持寄存器 (模拟量)
                        int reg_addr = mb_node->node.addr - 40001;
                        rc = modbus_read_registers(ctx, reg_addr, 1, &dest1);
                        if (rc == 1)
                        {
                            node_arr[i].old_val = node_arr[i].new_val;
                            node_arr[i].new_val.i_val = (int)dest1;
                            node_arr[i].ret = 0;
                            printf("寄存器[%d]读取成功: %s = %d\n",
                                   mb_node->node.addr, mb_node->node.name,
                                   (int)dest1);
                        }
                        else
                        {
                            node_arr[i].ret = -1;
                            fprintf(stderr, "寄存器读取失败: %s\n", modbus_strerror(errno));
                        }
                        break;
                    }

                    default:
                        fprintf(stderr, "未知数据类型: %d\n", mb_node->node.type);
                        break;
                    }
                    break;
                }
            }
            printf("采集数据完成\n");
        }
        // 上锁
        pthread_mutex_lock(&mutex);

        // 打印当前共享内存中的所有数据
        printf("\n当前共享内存数据:\n");
        printf("总节点数:        %d\n", *total);
        printf("------------------------------------------\n");
        for (int i = 0; i < *total; i++)
        {
            printf("节点 %d:\n", i);
            switch (node_arr[i].type)
            {
            case 1:
                printf("  value: %d\n", node_arr[i].new_val.b_val); // bool
                break;
            case 2:
                printf("  当前空调温度: %d\n", node_arr[i].new_val.i_val); // int
                break;
            case 3:
                printf("  value: %.2f\n", node_arr[i].new_val.f_val); // float
                break;
            default:
                printf("  值(未知类型)\n");
            }
        }
        // 解锁
        pthread_mutex_unlock(&mutex);

        sleep(1);
    }

    shm_del(&para);
    return NULL;
}